package com.faya.green.service.impl;

import com.faya.green.abnormal.ServiceException;
import com.faya.green.common.Constant;
import com.faya.green.dao.authority.PostUserDao;
import com.faya.green.dao.authority.RoleUserDao;
import com.faya.green.dao.sys.LogInfoDao;
import com.faya.green.dao.user.RelationshipDao;
import com.faya.green.dao.user.SubsidiaryUserDao;
import com.faya.green.dao.user.UserDao;
import com.faya.green.enumeration.ResultEnum;
import com.faya.green.enumeration.StatusEnum;
import com.faya.green.enumeration.UserFlagEnum;
import com.faya.green.model.*;
import com.faya.green.model.web.UserPostOrgWeb;
import com.faya.green.service.*;
import com.faya.green.utils.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 用户 ：LX
 * 创建时间： 2018/7/10. 23:55
 * 地点：广州
 * 目的: 用户业务逻辑层
 * 结果：
 */
@Service
public class UserServiceImpl implements UserService {

    //压制全部警告
    @SuppressWarnings("all")
    @Autowired
    private UserDao userDao;
    //压制全部警告
    @SuppressWarnings("all")
    @Autowired
    private LogInfoDao logInfoDao;
    //压制全部警告
    @SuppressWarnings("all")
    @Autowired
    private LogInfoService logInfoService;
    //压制全部警告
    @SuppressWarnings("all")
    @Autowired
    private PostUserDao postUserDao;
    //压制全部警告
    @SuppressWarnings("all")
    @Autowired
    private SubsidiaryUserDao subsidiaryUserDao;
    @SuppressWarnings("all")
    @Autowired
    private RelationshipDao relationshipDao;
    @SuppressWarnings("all")
    @Autowired
    private RoleUserDao roleUserDao;

    @Autowired
    private UserImgService userImgService;
    @Autowired
    private ResumeService resumeService;
    @Autowired
    private PunishService punishService;
    @Autowired
    private CommendService commendService;
    @Autowired
    private SubsidiaryUserService subsidiaryUserService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delUser(String userId, String postId) {
        User resultUser = userDao.findUserById(userId);
        if (resultUser == null){
            throw new ServiceException("数据错误，找不到用户");
        }
        if (resultUser.getId().equals(Constant.USER_BASE)){
            throw new ServiceException("该用户不能执行删除操作");
        }

        String imgHred = resultUser.getImgHred();
        userDao.delUserById(userId);
        PostUser postUser = postUserDao.getUserIdPostId(userId, postId);
        if (postUser != null){
            postUserDao.deletePostUser(postUser.getId());
        }

        //删除待办


        //履历
        List<Resume> resumeList = resumeService.getResumeByUserIdPubilc(userId, null);
        for (Resume resume : resumeList){
            resumeService.delResume(resume.getId());
        }

        //违纪
        List<Punish> punishList = punishService.getPunishByUserIdPubilc(userId, null);
        for (Punish punish : punishList){
            punishService.delPunish(punish.getId());
        }

        //嘉奖
        List<Commend> commendList = commendService.getCommendByUserId(userId);
        for (Commend commend : commendList){
            commendService.delCommend(commend.getId());
        }

        //关联用户
        List<Relationship> relationshipList = relationshipDao.getRelationshipByFather(userId);
        for (Relationship relationship : relationshipList){
            String son = relationship.getSon();
            subsidiaryUserService.delSubsidiaryUser(son);
        }

        //删除图片，图片最后删除，保证不会出现回滚的情况下，图片已经没了的问题
        List<UserImg> userImgList = userImgService.getUserImgList(userId);
        for (UserImg userImg : userImgList){
            userImgService.delUserImg(userImg.getId());
        }

        //删除原图片
        delImg(imgHred);
    }

    @Override
    public List<UserPostOrgWeb> getUserPostOrgWebByUid(String userId) {
        return userDao.getUserPostOrgWebByUid(userId);
    }

    @Override
    public List<UserPostOrgWeb> getUserPostOrgWebByCreateUser(String ucreateUser) {
        return userDao.getUserPostOrgWebByCreateUser(ucreateUser);
    }



    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addUserRole(String[] roleArr, String id){
        if (roleArr == null || roleArr.length == 0){
            throw new ServiceException("没有需要授予的角色，请选择角色后再试");
        }
        if (CommonUtils.checkNull(id)){
            throw new ServiceException("找不到要授权的用户");
        }

        for (String str : roleArr){
            RoleUser userRole = roleUserDao.getByUidRid(id, str);
            if (userRole != null){
                throw new ServiceException("该权限已经拥有，不能再次添加");
            }

            RoleUser roleUser = new RoleUser();
            roleUser.setId(UUID.randomUUID().toString());
            roleUser.setCreateTime(new Date());
            roleUser.setUpdateTime(new Date());
            roleUser.setRoleId(str);
            roleUser.setUserId(id);
            roleUser.setStatus(StatusEnum.STATUS_ADD.getCode());
            roleUserDao.addRoleUser(roleUser);
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delUserRole(String id, String uid) {
        if (CommonUtils.checkNull(id)){
            throw new ServiceException("权限ID不存在");
        }
        if (CommonUtils.checkNull(uid)){
            throw new ServiceException("用户ID不存在");
        }

        RoleUser roleUser = roleUserDao.getByUidRid(uid, id);
        if (roleUser != null){
            roleUserDao.delRoleUser(roleUser.getId());
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public User addUser(User user, MultipartFile file) {
        String logName = user.getLogName();
        if (!CommonUtils.checkNull(logName)){
            User logNameUser = userDao.findUserByLogName(logName);
            if (logNameUser != null){
                throw new ServiceException("注册的登录用户名重复!");
            }
        }

        //图片处理
        imgHandle(user, file);

        user.setId(UUID.randomUUID().toString());
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        user.setStatus(StatusEnum.STATUS_ADD.getCode());
        if ((Constant.CREATETYPEREG).equals(user.getCreateType())){
            //自创建的将自己的id赋予创建人
            user.setCreateUser(user.getId());
            user.setUpdateUser(user.getId());
            user.setFlag(UserFlagEnum.USER_FLAG_APPROVAL.getCode());

        } else if ((Constant.CREATETYPEADMIN).equals(user.getCreateType())) {
            Subject subject = SecurityUtils.getSubject();
            User useUser = (User)subject.getPrincipal();
            user.setCreateUser(useUser.getId());
            user.setUpdateUser(useUser.getId());
            user.setFlag(UserFlagEnum.USER_FLAG_USE.getCode());
        }

        //加盐 加密
        user.setSalt(UUID.randomUUID().toString());
        Md5Hash md5Password = new Md5Hash(user.getPassword(), user.getSalt(), 2);
        user.setPassword(md5Password.toString());

        //登录信息
        HttpServletRequest request = CommonUtils.getRequest();
        user.setIp(HttpUtil.getIpAddr(request));
        user.setLoginDate(new Date());

        //基础性数据赋值
        user.setIsTask(Constant.NO);
        user.setIsImg(Constant.NO);
        user.setIsResume(Constant.NO);
        user.setIsPunish(Constant.NO);
        user.setIsCommend(Constant.NO);
        user.setIsRelation(Constant.NO);

        userDao.addUser(user);
        return user;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public User login(String logName, String password) {

        LogInfo logInfo = logInfoService.addLogInfoSemifinished(logName);

        //登录的校验
        if (CommonUtils.checkNull(logName) || CommonUtils.checkNull(password)){
            logInfo.setLogStatus("1");
            logInfoDao.addLogInfo(logInfo);
            throw new AuthenticationException("用户名或密码为空");
        }

        User user = userDao.findUserByLogName(logName);
        if (user == null){
            logInfo.setLogStatus("1");
            logInfoDao.addLogInfo(logInfo);
            throw new UnknownAccountException("用户不存在");
        }

        String flag = user.getFlag();
        if (!CommonUtils.checkNull(flag)){
            if (flag.equals(UserFlagEnum.USER_FLAG_APPROVAL.getCode())){
                logInfo.setLogStatus("1");
                logInfoDao.addLogInfo(logInfo);
                throw new AuthenticationException("账号审批中，不能登录");
            } else if (flag.equals(UserFlagEnum.USER_FLAG_DISABLE.getCode())){
                logInfo.setLogStatus("1");
                logInfoDao.addLogInfo(logInfo);
                throw new DisabledAccountException("账号被禁用");
            } else if (flag.equals(UserFlagEnum.USER_FLAG_LOCK.getCode())){
                logInfo.setLogStatus("1");
                logInfoDao.addLogInfo(logInfo);
                throw new LockedAccountException("账号被锁定");
            }
        }

        Md5Hash md5Password = new Md5Hash(password, user.getSalt(), 2);
        if (!md5Password.toString().equals(user.getPassword())){
            logInfo.setLogStatus("1");
            logInfoDao.addLogInfo(logInfo);
            throw new IncorrectCredentialsException("密码错误");
        }

        //更新用户登录时间
        user.setLoginDate(new Date());
        userDao.updateUser(user);

        logInfoDao.addLogInfo(logInfo);
        return user;
    }


    /**
     * 备注：之前使用该代码测试，同一个service中调用其他的方法这样是否可以保证事务，发现这么写是会抛出异常的：
     *      Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.
     *   User createUser = ((UserService)AopContext.currentProxy()).addUser(user, file);
     *  可以证明，springboot直接调用是可以在同一个事务之中的
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addAutonomousUser(User user, MultipartFile file, String postId) {
        User createUser = addUser(user, file);
        PostUser postUser = new PostUser();
        postUser.setId(UUID.randomUUID().toString());
        postUser.setCreateTime(new Date());
        postUser.setUserId(createUser.getId());
        postUser.setPostId(postId);
        postUser.setUpdateTime(new Date());
        postUser.setStatus(StatusEnum.STATUS_ADD.getCode());
        postUserDao.addPostUser(postUser);
    }

    @Override
    public ResultJson getUserOnPostPage(String postId, Integer page, Integer limit) {
        if (CommonUtils.checkNull(postId)){
            throw new ServiceException("岗位ID为空");
        }

        if (page == null || limit == null || page < 0 || limit < 0){
            PageHelper.startPage(1, 10);
        } else {
            //这段代码表示，程序开始分页了，page默认值是1，pageSize默认是10，意思是从第1页开始，每页显示10条记录
            PageHelper.startPage(page, limit);
        }
        //分页助手会自动分页
        List<User> users = userDao.getUserByPostIdPageZH(postId);
        PageInfo<User> pageInfo = new PageInfo<User>(users);
        return new ResultJson(null, ResultEnum.RESULT_SUCCESS.getStatus(), "查询成功", pageInfo);
    }

    @Override
    public User getUserById(String id) {
        return userDao.findUserById(id);
    }

    /**
     * 图片处理，将图片保存到硬盘并进行裁剪等处理
     * @param user 用户
     * @param file 图片文件
     */
    private void imgHandle(User user, MultipartFile file){
        try {
            if (file != null && file.getSize() > 0){
                ImgUtils.headHandle(file, user);
            }
        } catch (ServiceException e) {
            throw new ServiceException(e.getMsg());
        } catch (IOException e) {
            throw new ServiceException("图片保存出错");
        }
    }

    /**
     * 图片删除
     * @param imgHred 图片的名字
     */
    private void delImg(String imgHred){
        //删除原图片
        String imgPath = PropertiesUtil.getPath("imgHred", PathUtil.getConfigPath());
        String path = imgPath + imgHred;

        //判断文件是否存在
        if ((FileUtils.fileIsExists(new File(path)))){
            FileUtils.delectFile(path);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateUser(User user, MultipartFile file, String postId) {
        User resultUser = userDao.findUserById(user.getId());
        if (resultUser == null){
            throw new ServiceException("数据错误，找不到用户");
        }
        if (resultUser.getId().equals(Constant.USER_BASE)){
            throw new ServiceException("该用户不能执行更新操作");
        }

        String imgHred = user.getImgHred();
        //判断密码是否修改
        String passwordResult = resultUser.getPassword();
        if (!passwordResult.equals(user.getPassword())){
            user.setSalt(UUID.randomUUID().toString());
            Md5Hash md5Password = new Md5Hash(user.getPassword(), user.getSalt(), 2);
            user.setPassword(md5Password.toString());
        }

        //图片处理
        imgHandle(user, file);

        //删除原图片
        if (file != null && file.getSize() > 0){
            delImg(imgHred);
        }

        user.setUpdateTime(new Date());
        Subject subject = SecurityUtils.getSubject();
        User useUser = (User)subject.getPrincipal();
        user.setUpdateUser(useUser.getId());
        userDao.updateUser(user);

        // 删除关系
        /*PostUser postUser = postUserDao.getPostUserByUserId(user.getId());
        if (postUser != null){
            postUserDao.deletePostUser(postUser.getId());
        }*/
    }



}
